home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / N-P / NIFTY / myCShell / about.c next >
Encoding:
C/C++ Source or Header  |  1991-12-27  |  26.6 KB  |  1,079 lines  |  [TEXT/KAHL]

  1. /*********************************************************
  2.  "about.c"
  3.  
  4.  by Joe Pillera [MacTutor, January 1990]
  5.  
  6.  using Symantec's "THINK C", v 5.00
  7.  *********************************************************/
  8.  
  9.  
  10. #include <string.h>
  11. #include <Traps.h>
  12.  
  13. #include "protos"
  14.  
  15. #include "globals.h"
  16. #include "extern.h"
  17.  
  18. #include "about.h"
  19. #include "floatingWindow.h"
  20.  
  21.  
  22.  
  23.  
  24.     HelpInfoHdl        hHTBL;
  25.     ListHandle        my_List_Handle;
  26.     Rect            List_Rect, Display_Rect, Scroller_Rect;
  27.     Rect            Dest_Rect, View_Rect, Frame_Rect;
  28.     short            Current_Topic;
  29.     short            Current_Pict;
  30.     DialogPtr        helpPtr;
  31.     TEHandle        myTEHandle;
  32.     Handle            myTextHandle;
  33.     ViewMode        Last_Type;
  34.     ControlHandle    hScrollBar;
  35.     short            First_Menu, Last_Menu;
  36.     short            START, FINISH, lastHit;
  37.     HelpTopic        topics[MAX_TOPICS];
  38.     /*
  39.     ViewMode        screen_mode[MAX_TOPICS];
  40.     short            resource_start[MAX_TOPICS];
  41.     short            resource_end[MAX_TOPICS];
  42.     Str255            topic_name[MAX_TOPICS];
  43.     */
  44.     Boolean            newStyleTE, newStyle;
  45.     Handle            myStylHandle;
  46.     short            halfPagePix, currentTopLine, halfPageTopLine, maxTopLine;
  47.     Cell            lastCell;
  48.     short            pageCells;
  49.  
  50.  
  51.  
  52.  
  53. void    H_Add_List_String (ListHandle theList, Str255 theString)    {
  54. /* Made this hummer general enough to accomodate multiple columns.
  55. ** Fill one complete row first before going onto another.          */
  56.  
  57.         short            theRow    /* The row to add */, nCols;
  58.         static Cell        theCell = {0,0};
  59.         Boolean            newRow;
  60.         
  61.  
  62.     if (theList == nil)        return;
  63.     
  64.     nCols = (**theList).dataBounds.right - 1;    /* Zero-based */
  65.     if (theCell.h > nCols)        theCell.h = 0;
  66.     
  67.     newRow = (theCell.h == 0);
  68.     if (newRow)        {
  69.         theRow = LAddRow(1, 32000, theList);
  70.         theCell.v = theRow;
  71.     }
  72.     
  73.     LSetCell(theString + 1, theString[0], theCell, theList);
  74.  /* H_Refresh_Topics draws by calling LUpdate: */
  75.  // LDraw(theCell, theList);
  76.  
  77.      theCell.h++;            // ... for NEXT time through.
  78.  
  79. }    /* H_Add_List_String */
  80.  
  81.  
  82.  
  83. void    Create_Help (void)    {
  84.  
  85.         short        DType;        /* Item type. */
  86.         Point        cSize;
  87.         Rect        viewRect;
  88.         Rect        dataBounds;
  89.         short        defaultProcID = 0, htAdjust, viewHt;
  90.         Handle        DItem;
  91.         short        index;
  92.         short        bType;        /* ... for Next/Previous Buttons: */
  93.         Handle        bHandle;
  94.         Rect        bBox;
  95.         PenState    pnState;
  96.         FontInfo    helpFont;
  97.         Cell        firstCell = {0,0};
  98.         
  99.         
  100.     // Setup pointers to the intro screen:
  101.     Current_Topic = START;        /* = Initial_Picture from Init_Help(). */
  102.     Current_Pict = topics[Current_Topic].resource_start;
  103.         
  104.     // Bring up the HELP screen:
  105.     helpPtr = GetNewDialog(Help_Window, nil, (WindowPtr)-1);
  106.     SetPort(helpPtr);
  107.  // FrameDefaultButton(helpPtr);  --  called within H_Handle_Update()
  108.     
  109.  /* // Hide Next & Previous Buttons for Intro Screen: -- H_Display_Pict does this !!
  110.     GetDItem(helpPtr, Next_Button, &bType, &bHandle, &bBox);
  111.     HideControl((ControlHandle)bHandle);
  112.     GetDItem(helpPtr, Prev_Button, &bType, &bHandle, &bBox);
  113.     HideControl((ControlHandle)bHandle);
  114.     
  115.     // Disable Next & Previous Buttons: -- H_Handle_List_Event does this !!
  116.     H_Set_Button_State(Next_Button, false);
  117.     H_Set_Button_State(Prev_Button, false);                                            */
  118.     
  119.     // Now ... build the list:
  120.     GetDItem(helpPtr, Topics_Area, &DType, &DItem, &List_Rect);
  121.     
  122.     /* Compute list area (a user-item) by
  123.        subtracting space for the Scroll Bar(s): */
  124.     viewRect = List_Rect;
  125.     viewRect.right = viewRect.right + frame - scrollWidth;
  126.     viewRect.bottom = viewRect.bottom + frame - scrollHeight;
  127.     
  128.     SetRect(&dataBounds, 0, 0, 1, 0);    /* one column list */
  129.     
  130.     GetPenState(&pnState);
  131.     ;
  132.     cSize.h = viewRect.right - viewRect.left;
  133.     PenNormal();
  134.     TextFont(geneva);
  135.     TextSize(10);
  136.     GetFontInfo(&helpFont);
  137.     cSize.v = helpFont.ascent + helpFont.descent + helpFont.leading;
  138.  
  139.     // Adjust heights of rView & overall List_Rect to be a multiple of cSize.v:
  140.  
  141.     viewHt = viewRect.bottom - viewRect.top;
  142.     htAdjust = viewHt % cSize.v;
  143.     viewRect.bottom = viewRect.bottom - htAdjust;
  144.     List_Rect.bottom = List_Rect.bottom - htAdjust;
  145.     
  146.     // Redo the two rects in the gDynamicBalloons[] array just in case:
  147.     gDynamicBalloons[(Topics_Area - 1)*2 + 1].dynamicR = List_Rect;
  148.     gDynamicBalloons[(Topics_Area - 1)*2 + 2].dynamicR = List_Rect;
  149.     
  150.     // Make the list:
  151.     my_List_Handle = LNew(&viewRect,        //    rView
  152.                           &dataBounds,
  153.                           cSize,
  154.                           defaultProcID,
  155.                           helpPtr,            //    the window
  156.                           true,                //    draw it
  157.                           true,                //    has Grow Box < NON-functional >
  158.                           true,                //    horizontal ScrollBar
  159.                           true);            //    vertical ScrollBar
  160.     (*my_List_Handle)->selFlags = lOnlyOne + lNoNilHilite;
  161.     (*my_List_Handle)->refCon = (long) true;    /* has Grow Box */
  162.     ;
  163.     SetPenState(&pnState);
  164.     
  165.     // Fill in the initial list contents ~~ begin after the Intro PICT:
  166.     for (index = START + 1; index <= FINISH; index++)
  167.         H_Add_List_String(my_List_Handle, topics[index].topic_name);
  168.     ;
  169.  // LSetSelect(true, firstCell, my_List_Handle);  --  Nope, let user do it !!
  170.     SetPt(&lastCell,
  171.           (**my_List_Handle).dataBounds.right - 1,        // Cell # is one less.
  172.           (**my_List_Handle).dataBounds.bottom - 1);
  173.     pageCells = viewHt / cSize.v;
  174.         
  175.     LDoDraw(true, my_List_Handle);
  176.     
  177.     // Compute critical info once & for all:
  178.     GetDItem(helpPtr, Display_Area, &DType, &DItem, &Display_Rect);
  179.     
  180.     Scroller_Rect = Display_Rect;
  181.     Scroller_Rect.left = Scroller_Rect.right - scrollWidth;
  182.     
  183.     Frame_Rect = Display_Rect;
  184.     Frame_Rect.right = Frame_Rect.right + frame - growBoxSize;
  185.  
  186.     View_Rect = Frame_Rect;
  187.     InsetRect(&View_Rect, 4, 4);
  188.     halfPagePix = (View_Rect.bottom - View_Rect.top) >> 1;
  189.     
  190.     Dest_Rect = View_Rect;
  191.     Dest_Rect.bottom = 10000;
  192.  
  193.     // Wait till last to show window so that we don't see
  194.     // cell-after-cell being drawn.  H_Display_Pict sets up
  195.     // the showing/hiding of the Previous/Next Buttons:
  196.     H_Display_Pict(Current_Pict);        /* Sets Last_Type = pict. */
  197.     TShowWindow(helpPtr);
  198.     
  199.     /* Remember ... we can close the daggum thing ... ARRGH !!! */
  200.     lastHit = -1;
  201.     
  202. }    /* Create_Help */
  203.  
  204.  
  205.  
  206. void    H_Dialog_String (DialogPtr dlg, short theItem, Str255 theString)    {
  207.  
  208.         short    iType;
  209.         Handle    iHandle;
  210.         Rect    iBox;
  211.         
  212.         
  213.     GetDItem(dlg, theItem, &iType, &iHandle, &iBox);
  214.     SetIText(iHandle, theString);
  215.  
  216. }    /* H_Dialog_String */
  217.  
  218.  
  219.  
  220. void    H_Display_Pict (short thisPict)        {
  221.  
  222.         PicHandle    thePict;
  223.         short        bType, pType;
  224.         Handle        bHandle, pHandle;
  225.         Rect        bBox, pBox, pictRect;
  226.         PicHandle    newPict;
  227.         RgnHandle    oldClip;
  228.         short        mesg_this_one;            /* Screen we're on now. */
  229.         short        mesg_max_one;            /* Total # of screens in HelpTopic. */
  230.         Str255        s1, s2, s3, s4, s5;
  231.         
  232.     
  233.     if (Last_Type == pict)    {
  234.         thePict = GetPicture(Current_Pict);
  235.         if (thePict != nil)        ReleaseResource(thePict);
  236.     }
  237.     else if (Last_Type == text)        {
  238.         if (newStyle)    {
  239.             HUnlock(myStylHandle);
  240.             ReleaseResource(myStylHandle);
  241.         }
  242.         HUnlock(myTextHandle);
  243.         ReleaseResource(myTextHandle);
  244.         DisposeControl(hScrollBar);
  245.         HUnlock(myTEHandle);
  246.         TEDispose(myTEHandle);
  247.     }
  248.     Last_Type = noMode;                    /* ... in case we return early. */
  249.     
  250.     // Show or Hide the Next & Previous Buttons:
  251.     if ( (topics[Current_Topic].resource_end -
  252.           topics[Current_Topic].resource_start) >= 1)    {
  253.         GetDItem(helpPtr, Next_Button, &bType, &bHandle, &bBox);
  254.         ShowControl((ControlHandle)bHandle);
  255.         GetDItem(helpPtr, Prev_Button, &bType, &bHandle, &bBox);
  256.         ShowControl((ControlHandle)bHandle);          
  257.     }
  258.     else    {
  259.         GetDItem(helpPtr, Next_Button, &bType, &bHandle, &bBox);
  260.         HideControl((ControlHandle)bHandle);
  261.         GetDItem(helpPtr, Prev_Button, &bType, &bHandle, &bBox);
  262.         HideControl((ControlHandle)bHandle);          
  263.     }
  264.     
  265.     // Compute which picture to display:
  266.     mesg_this_one = thisPict - topics[Current_Topic].resource_start + 1;
  267.     mesg_max_one = topics[Current_Topic].resource_end -
  268.                    topics[Current_Topic].resource_start + 1;
  269.     
  270.     newPict = GetPicture(thisPict);        /* Display the picture ... */
  271.     if (newPict == nil)        {
  272.         if (thisPict == topics[Initial_Picture].resource_start)
  273.             H_Error_Message(err_intro_pict);
  274.         else
  275.             H_Error_Message(err_no_pict);
  276.         return;
  277.     }
  278.     
  279.     InvalRect(&Display_Rect);
  280.     /* ... so H_HandleUpdate() can take care of this:
  281.     pBox = Display_Rect;
  282.     EraseRect(&pBox);
  283.     pictRect = (**newPict).picFrame;
  284.     CenterRects(&pictRect, &pBox);
  285.     oldClip = NewRgn();
  286.     GetClip(oldClip);
  287.     ClipRect(&pBox);
  288.     DrawPicture(newPict, &pictRect);
  289.     SetClip(oldClip);
  290.     DisposeRgn(oldClip);
  291.     */
  292.  
  293.     if (thisPict == topics[Initial_Picture].resource_start)
  294.         H_User_Message("\pStatus:  <Intro PICTure>");
  295.     else    {
  296.         NumToString(mesg_this_one, s1);
  297.         NumToString(mesg_max_one, s2);
  298.         pStrCat("\pStatus:  Screen ", s1, s3);
  299.         pStrCat(s3, "\p of ", s4);
  300.         pStrCat(s4, s2, s5);
  301.         H_User_Message(s5);
  302.     }
  303.     
  304.     Current_Pict = thisPict;
  305.     Last_Type = pict;
  306.         
  307. }    /* H_Display_Pict */
  308.  
  309.  
  310.  
  311. void    H_Display_Text (void)    {
  312.  
  313.         PicHandle        thePict;
  314.         short            bType, excess;
  315.         Handle            bHandle;
  316.         Rect            bBox;
  317.  
  318.         
  319.     if (Last_Type == pict)    {
  320.         thePict = GetPicture(Current_Pict);
  321.         if (thePict != nil)        ReleaseResource(thePict);
  322.     }
  323.     else if (Last_Type == text)        {
  324.         if (newStyle)    {
  325.             HUnlock(myStylHandle);
  326.             ReleaseResource(myStylHandle);
  327.         }
  328.         HUnlock(myTextHandle);
  329.         ReleaseResource(myTextHandle);
  330.         DisposeControl(hScrollBar);
  331.         HUnlock(myTEHandle);
  332.         TEDispose(myTEHandle);
  333.     }
  334.     Last_Type = noMode;
  335.     
  336.     myTextHandle = GetResource('TEXT', topics[Current_Topic].resource_start);
  337.     if (myTextHandle == nil)    {
  338.         H_Error_Message(err_no_text);
  339.         return;
  340.     }
  341.     MoveHHi(myTextHandle);
  342.     HLock(myTextHandle);
  343.     
  344.     if (newStyleTE)        {
  345.         myStylHandle = GetResource('styl', topics[Current_Topic].resource_start);
  346.         if (myStylHandle != nil)    {
  347.             MoveHHi(myStylHandle);
  348.             HLock(myStylHandle);
  349.         }
  350.     }
  351.     newStyle = newStyleTE && (myStylHandle != nil);
  352.  
  353.     // Hide Next & Previous Buttons:
  354.     
  355.     GetDItem(helpPtr, Next_Button, &bType, &bHandle, &bBox);
  356.     HideControl((ControlHandle)bHandle);
  357.     GetDItem(helpPtr, Prev_Button, &bType, &bHandle, &bBox);
  358.     HideControl((ControlHandle)bHandle);
  359.     
  360.     EraseRect(&Display_Rect);
  361.     
  362.     hScrollBar = GetNewControl(Help_Window, helpPtr);
  363.  
  364.     // Frame the text box:
  365.     
  366.     InvalRect(&Frame_Rect);
  367.     /* ... so H_HandleUpdate() can take care of this:
  368.     MoveTo(Frame_Rect.right, Frame_Rect.top);
  369.     LineTo(Frame_Rect.left, Frame_Rect.top);
  370.     LineTo(Frame_Rect.left, Frame_Rect.bottom - frame);
  371.     LineTo(Frame_Rect.right, Frame_Rect.bottom - frame);
  372.     */
  373.  
  374.     // Create & fill-in a Text Edit Handle:
  375.  
  376.     if (newStyle)
  377.         myTEHandle = TEStylNew(&Dest_Rect, &View_Rect);        // A new TEHandle.
  378.     else
  379.         myTEHandle = TENew(&Dest_Rect, &View_Rect);
  380.     MoveHHi(myTEHandle);
  381.     HLock(myTEHandle);
  382.     if (newStyle)
  383.         TEStylInsert(*myTextHandle, SizeResource(myTextHandle),
  384.                      (StScrpHandle) myStylHandle, myTEHandle);
  385.     else
  386.         TEInsert(*myTextHandle, SizeResource(myTextHandle), myTEHandle);
  387.  // TEUpdate(&View_Rect, myTEHandle); -- in H_HandleUpdate()
  388.     H_User_Message("\pStatus:  <Text Mode>");
  389.     
  390.     // Set-up scrolling parameters:
  391.  
  392.     if (newStyle)
  393.         excess = TEGetHeight((*myTEHandle)->nLines, 1, myTEHandle) -
  394.                  (View_Rect.bottom - View_Rect.top);
  395.     else
  396.         excess = ((*myTEHandle)->nLines * (*myTEHandle)->lineHeight) -
  397.                  (View_Rect.bottom - View_Rect.top);
  398.                  
  399.     if (excess > 0)        {
  400.         SetCtlMax(hScrollBar, excess);
  401.      // HiliteControl(hScrollBar, ON);   --  contrlMax > 0 does this.
  402.         maxTopLine = GetLineNbr(newStyle, myTEHandle, excess);
  403.     }
  404.     else    {
  405.         SetCtlMax(hScrollBar, 0);
  406.      // HiliteControl(hScrollBar, OFF);  --  zip contrlMax does this !!
  407.      // maxTopLine = 1;  --  doesn't matter because Scroll Bar is inactive.
  408.     }
  409.         
  410.     currentTopLine = 1;            /* Begin at the begin. */
  411.     halfPageTopLine = GetLineNbr(newStyle, myTEHandle, halfPagePix);
  412.     
  413.     Last_Type = text;
  414.     
  415. }    /* H_Display_Text */
  416.  
  417.  
  418.  
  419. void    H_Error_Message (ErrorTypes theError)    {
  420.         
  421.         short        bType;
  422.         Handle        bHandle;
  423.         Rect        bBox;
  424.         DialogPtr    alert;
  425.         GrafPtr        savePort;
  426.         short        whatHit;
  427.         
  428.         
  429.     alert = GetNewDialog(Help_Error, nil, (WindowPtr)-1);
  430.     ;
  431.     GetDItem(alert, ((DialogPeek)alert)->aDefItem, &bType, &bHandle, &bBox);
  432.     InsetRect(&bBox, -6, -6);
  433.     SetDItem (alert,
  434.               ((DialogPeek)alert)->aDefItem + 1,    // = my user item.
  435.               userItem,
  436.               (Handle)&H_Frame_Alert_Button,
  437.               &bBox);
  438.     ;
  439.     SetPort(alert);
  440.     DisplayWindow(alert, true);
  441.     ClipRect(&alert->portRect);
  442.     SysBeep(10);
  443.     
  444.     switch    (theError)    {
  445.         case err_no_HTBL:
  446.             H_Dialog_String(alert, 4, "\pNo HTBL (Help Table resource)");
  447.             H_Dialog_String(alert, 5, "\pwas found in your resource fork!!");
  448.             H_Dialog_String(alert, 6, "\pPlease create one immediately.");
  449.             break;
  450.             
  451.         case err_min_res:
  452.             H_Dialog_String(alert, 4, "\pYou should have at least an intro");
  453.             H_Dialog_String(alert, 5, "\pscreen and one Help screen for your");
  454.             H_Dialog_String(alert, 6, "\pHelp system.");
  455.             break;
  456.             
  457.         case err_intro_pict:
  458.             H_Dialog_String(alert, 4, "\pThis program assumes that the intro");
  459.             H_Dialog_String(alert, 5, "\pscreen is always a picture!!");
  460.             H_Dialog_String(alert, 6, "\pPlease change the screen.");
  461.             break;
  462.             
  463.         case err_bad_type:
  464.             H_Dialog_String(alert, 4, "\pScreen types are either PICT or");
  465.             H_Dialog_String(alert, 5, "\pTEXT.  One of your HTBL fields for");
  466.             H_Dialog_String(alert, 6, "\pscreen types is incorrect.");
  467.             break;
  468.             
  469.         case err_no_pict:
  470.             H_Dialog_String(alert, 4, "\pThe PICT(s) for this topic do not");
  471.             H_Dialog_String(alert, 5, "\pexist??  Very UNcool!!  I will exit");
  472.             H_Dialog_String(alert, 6, "\pto the Finder rather than crash ...");
  473.             break;
  474.             
  475.         case err_no_text:
  476.             H_Dialog_String(alert, 4, "\pThe TEXT for this topic does not");
  477.             H_Dialog_String(alert, 5, "\pexist??  Very UNcool!!  I will exit");
  478.             H_Dialog_String(alert, 6, "\pto the Finder rather than crash ...");
  479.             break;
  480.             
  481.         default:    break;
  482.         
  483.     }    /* end switch */
  484.     
  485.     ModalDialog((ProcPtr)&H_Modal_Filter, &whatHit);
  486.     DisposDialog(alert);
  487.     
  488.     if (hHTBL != nil)    {
  489.         /* Not gone, for example, if err_intro_pict which
  490.         ** would cause a premature exit from Init_Help()  */
  491.         HUnlock(hHTBL);
  492.         ReleaseResource(hHTBL);
  493.     }
  494.     
  495.     DoQuit();
  496.  
  497. }    /* H_Error_Message */
  498.  
  499.  
  500.  
  501. void    H_Handle_List_Event (short whatHit)        {
  502.  
  503.  
  504.     // Because the listed topics[] start at index = 1.
  505.     // The Intro screen, a PICT, has an index = 0:
  506.     Current_Topic = whatHit + 1;
  507.     
  508.     H_Set_Button_State(Prev_Button, false);
  509.     
  510.     if (topics[Current_Topic].resource_end - topics[Current_Topic].resource_start)
  511.             H_Set_Button_State(Next_Button, true);
  512.     else    H_Set_Button_State(Next_Button, false);
  513.     
  514.     if (topics[Current_Topic].screen_mode == pict)
  515.         H_Display_Pict(topics[Current_Topic].resource_start);
  516.     else if (topics[Current_Topic].screen_mode == text)
  517.         H_Display_Text();
  518.     else
  519.         SysBeep(10);
  520.  
  521. }    /* H_Handle_List_Event */
  522.  
  523.  
  524.  
  525. void    H_Handle_Update (void)    {
  526.  
  527.         short            pType;
  528.         Handle            pHandle;
  529.         Rect            pBox, pictRect;
  530.         PicHandle        thePict;
  531.         RgnHandle        oldClip;
  532.         RGBColor        foreColor;
  533.         AuxCtlHandle    acHndl;
  534.         CCTabHandle        ccTable;
  535.         
  536.         
  537.  // if (helpPtr == nil)        return;  --  routine NOT called if so.
  538.  
  539.  // SetPort(helpPtr);  --  already set in main HandleUpdate()
  540.  
  541.     H_Refresh_Topics();
  542.     FrameDefaultButton(helpPtr);
  543.     
  544.     if (topics[Current_Topic].screen_mode == text)        {
  545.         if (gMac2)        {
  546.             GetForeColor(&foreColor);
  547.             if (GetAuxCtl(hScrollBar, &acHndl))        {
  548.                 ccTable = (**acHndl).acCTable;
  549.                 RGBForeColor(& ((**ccTable).ctTable)[cFrameColor].rgb );
  550.             }
  551.         }    /* gMac2 */
  552.         ;
  553.         // Three sides of the frame:
  554.         MoveTo(Frame_Rect.right, Frame_Rect.top);
  555.         LineTo(Frame_Rect.left, Frame_Rect.top);
  556.         /* _LineTo draws on OUTSIDE of point: */
  557.         LineTo(Frame_Rect.left, Frame_Rect.bottom - frame);
  558.         LineTo(Frame_Rect.right, Frame_Rect.bottom - frame);
  559.         ;
  560.         if (gMac2)    RGBForeColor(&foreColor);
  561.         
  562.         TEUpdate(&View_Rect, myTEHandle);
  563.     }    /* text item */
  564.     
  565.     else if (topics[Current_Topic].screen_mode == pict)    {
  566.         thePict = GetPicture(Current_Pict);
  567.         if (thePict == nil)        SysBeep(10);
  568.         else    {
  569.             pBox = Display_Rect;
  570.             EraseRect(&pBox);
  571.             pictRect = (**thePict).picFrame;
  572.             CenterRects(&pictRect, &pBox);
  573.             oldClip = NewRgn();
  574.             GetClip(oldClip);
  575.             ClipRect(&pBox);
  576.             DrawPicture(thePict, &pictRect);
  577.             SetClip(oldClip);
  578.             DisposeRgn(oldClip);
  579.         }    /* Got a picture */
  580.     }    /* pict item */
  581.     
  582.     DrawDialog(helpPtr);
  583.     
  584. }    /* H_Handle_Update */
  585.  
  586.  
  587.  
  588. void    Init_Help (void)    {
  589.  
  590.         char            *HTBL_mastPtr;
  591.         short            index;
  592.         long            mode;
  593.         char            ch;
  594.         
  595.         
  596.     /* Haven't called Create_Help() yet.  Placed at
  597.     ** start of routine just in case we die early !! */
  598.     helpPtr = nil;
  599.     Last_Type = noMode;
  600.     
  601.     hHTBL = (HelpInfoHdl)GetResource('HTBL', HTBL_RSRC);
  602.     if (hHTBL == nil)    {
  603.         H_Error_Message(err_no_HTBL);
  604.         return;
  605.     }
  606.     MoveHHi(hHTBL);
  607.     HLock(hHTBL);
  608.     
  609.     HTBL_mastPtr = (char*) *hHTBL;
  610.     First_Menu = Parse_Int((varedPtr) &HTBL_mastPtr);
  611.     Last_Menu = Parse_Int((varedPtr) &HTBL_mastPtr);
  612.     START = Initial_Picture;
  613.     FINISH = Parse_Int((varedPtr) &HTBL_mastPtr);        /* Zero-based count */
  614.  
  615.     // Enough Help screens to proceed ???  Must have at least 2:
  616.     if (FINISH < 1)        {
  617.         H_Error_Message(err_min_res);
  618.         return;
  619.     }
  620.     if (FINISH > MAX_TOPICS -1)        FINISH = MAX_TOPICS - 1;
  621.     
  622.     // Now, loop through all the screens:
  623.     for (index = START; index <= FINISH; index++)
  624.     {
  625.         mode = Parse_OSType((varedPtr) &HTBL_mastPtr);
  626.         ch = (char)(mode >> 24);
  627.         if ((ch == 'p') || (ch == 'P'))
  628.             topics[index].screen_mode = pict;
  629.         else if ((ch == 't') || (ch == 'T'))
  630.             topics[index].screen_mode = text;
  631.         else    {
  632.             H_Error_Message(err_bad_type);
  633.             return;
  634.         }
  635.         
  636.         if ((index == START) && (topics[index].screen_mode != pict))    {
  637.             H_Error_Message(err_intro_pict);
  638.             return;
  639.         }
  640.             
  641.         // Get resource bounds:
  642.         topics[index].resource_start = Parse_Int((varedPtr) &HTBL_mastPtr);
  643.         topics[index].resource_end = Parse_Int((varedPtr) &HTBL_mastPtr);
  644.         
  645.         Parse_String ( (char*)topics[index].topic_name, (varedPtr) &HTBL_mastPtr );
  646.     }
  647.     
  648.     /* All we really needed to do here was fill in our topics[]
  649.        array so we can immediately dispose of our Handle.        */
  650.     HUnlock(hHTBL);
  651.     ReleaseResource(hHTBL);
  652.     hHTBL = nil;                /* Mark as gone !! See H_Error_Message */
  653.     
  654.     // Now, fill in our dynamic balloon array:
  655.     
  656.     for (index = OK_Button;
  657.          index <= Message_Area * 2 /* 2 strings per DLOG item */;
  658.          index++)    {
  659.         gDynamicBalloons[index].dynamicStrID = Help_Window;
  660.         gDynamicBalloons[index].dynamicStrIndex = index;
  661.     }
  662.     
  663.     index = OK_Button;
  664.     SetRect(&gDynamicBalloons[index].dynamicR, 352, 260, 412, 280);
  665.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  666.     
  667.     index = (Topics_Area - 1)*2 + 1;
  668.     SetRect(&gDynamicBalloons[index].dynamicR, 305,  32, 465, 185);
  669.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  670.     
  671.     index = (Display_Area - 1)*2 + 1;
  672.     SetRect(&gDynamicBalloons[index].dynamicR, 10,  10, 290, 290);
  673.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  674.     
  675.     index = (Next_Button - 1)*2 + 1;
  676.     SetRect(&gDynamicBalloons[index].dynamicR, 405, 225, 465, 245);
  677.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  678.     
  679.     index = (Prev_Button - 1)*2 + 1;
  680.     SetRect(&gDynamicBalloons[index].dynamicR, 305, 225, 385, 245);
  681.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  682.     
  683.     index = (Mast_Head - 1)*2 + 1;
  684.     SetRect(&gDynamicBalloons[index].dynamicR, 305,  10, 465,  27);
  685.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  686.     
  687.     index = (Message_Area - 1)*2 + 1;
  688.     SetRect(&gDynamicBalloons[index].dynamicR, 305, 195, 465, 215);
  689.     gDynamicBalloons[index + 1].dynamicR = gDynamicBalloons[index].dynamicR;
  690.     
  691.     newStyleTE = StylizedTE();                // Whoops ... almost forgot !!
  692.  
  693. }    /* Init_Help */
  694.  
  695.  
  696.  
  697. void    Kill_Help_Window (void)    {
  698.  
  699.         PicHandle    thePict;
  700.  
  701.     
  702.     if (helpPtr == nil)        return;
  703.     
  704.     if (Last_Type == pict)    {
  705.         thePict = GetPicture(Current_Pict);
  706.         if (thePict != nil)        ReleaseResource(thePict);
  707.     }
  708.     else if (Last_Type == text)        {
  709.         if (newStyle)    {
  710.             HUnlock(myStylHandle);
  711.             ReleaseResource(myStylHandle);
  712.         }
  713.         HUnlock(myTextHandle);
  714.         ReleaseResource(myTextHandle);
  715.         DisposeControl(hScrollBar);
  716.         HUnlock(myTEHandle);
  717.         TEDispose(myTEHandle);
  718.     }
  719.     Last_Type = noMode;
  720.     
  721.     LDispose(my_List_Handle);
  722.     
  723.     THideWindow(helpPtr);
  724.     DisposDialog(helpPtr);
  725.     helpPtr = nil;                /* Mark as gone. */
  726.  
  727. }    /* Kill_Help_Window */
  728.  
  729.  
  730.  
  731. pascal void    H_Scroll_Filter (ControlHandle ctl, short thePart)    {
  732.  
  733.         short            min, max;                // ScrollBar's min & max values.
  734.         short            newValue, oldValue, linePix;
  735.         long            finalTicks;
  736.         
  737.         
  738.     min = (*hScrollBar)->contrlMin;
  739.     max = (*hScrollBar)->contrlMax;
  740.     oldValue = GetCtlValue(hScrollBar);
  741.     newValue = oldValue;
  742.     
  743.     linePix = GetLineHeight(newStyle, myTEHandle, currentTopLine);
  744.  
  745.     switch (thePart)    {
  746.     
  747.         case inUpButton:
  748.             newValue -= linePix;
  749.             if (newValue < min)        {
  750.                     newValue = min;
  751.                     currentTopLine = 1;
  752.             }
  753.             else    --currentTopLine;
  754.             break;
  755.     
  756.         case inDownButton:
  757.             newValue += linePix;
  758.             if (newValue > max)        {
  759.                     newValue = max;
  760.                     currentTopLine = maxTopLine;
  761.             }
  762.             else    currentTopLine++;
  763.             break;
  764.     
  765.         case inPageUp:
  766.             newValue -= halfPagePix;
  767.             if (newValue < min)        {
  768.                     newValue = min;
  769.                     currentTopLine = 1;
  770.             }
  771.             else    currentTopLine -= halfPageTopLine;
  772.             break;
  773.     
  774.         case inPageDown:
  775.             newValue += halfPagePix;
  776.             if (newValue > max)        {
  777.                     newValue = max;
  778.                     currentTopLine = maxTopLine;
  779.             }
  780.             else    currentTopLine += halfPageTopLine;
  781.             break;
  782.     
  783.         default:    break;
  784.     
  785.     }    /* end switch */
  786.     
  787.     if (newValue != oldValue)    {        /* Avoid blinking Thumb. */
  788.         SetCtlValue(hScrollBar, newValue);
  789.         Delay(2, &finalTicks);
  790.         H_Scroll_Text(oldValue, newValue);
  791.     }
  792.  
  793. }    /* H_Scroll_Filter */
  794.  
  795.  
  796.  
  797. short    Parse_Int (varedPtr addrMPtr)    {
  798.  
  799.         short            result = 0;
  800.         unsigned char    hiByte, loByte;
  801.     
  802.     
  803.     hiByte = (unsigned char) *( (*addrMPtr)++ );    // Increment the Master Pointer.
  804.     loByte = (unsigned char) *( (*addrMPtr)++ );
  805.     
  806.     result = result | hiByte;
  807.     result = (result << 8) | loByte;
  808.     
  809.     return (result);
  810.  
  811. }    /* Parse_Int */
  812.  
  813.  
  814.  
  815. long    Parse_OSType (varedPtr addrMPtr)    {
  816.  
  817.         long    result = 0;
  818.         char    nextByte;
  819.         short    index;
  820.     
  821.     
  822.     // Loop through 4 bytes:
  823.     for (index = 1; index <= sizeof(long); index++)    {
  824.         nextByte = *( (*addrMPtr)++ );
  825.         result = (result << 8) | (long) nextByte;
  826.     }
  827.  
  828.     return (result);
  829.  
  830. }    /* Parse_OSType */
  831.  
  832.  
  833. void    Parse_String (char *destStr, varedPtr addrSrcStrPtr)    {
  834.  
  835.         short        len = *destStr++ = *( (*addrSrcStrPtr)++ );
  836.         Boolean        wordAlign = ((len % 2) == 0);
  837.         
  838.     while (--len >= 0)    *destStr++ = *((*addrSrcStrPtr)++);
  839.     if (wordAlign)        (*addrSrcStrPtr)++;
  840.  
  841. }    /* Parse_String */
  842.  
  843.  
  844.  
  845. void    H_Refresh_Topics (void)    {
  846.  
  847.         Rect        tempRect;
  848.         PenState    pnState;
  849.         RgnHandle    oldClip;
  850.         
  851.         
  852.     LUpdate(helpPtr->visRgn, my_List_Handle);
  853.     tempRect = List_Rect;
  854.     InsetRect(&tempRect, -frame, -frame);
  855.     FrameRect(&tempRect);
  856.  
  857.     H_DrawGrowIcon(my_List_Handle);
  858.     
  859. }    /* H_Refresh_Topics */
  860.  
  861.  
  862.  
  863. void    H_Scroll_Picture (short whatHit)    {
  864.  
  865.         short    theMax, theMin;
  866.         
  867.         
  868.     theMin = topics[Current_Topic].resource_start;
  869.     theMax = topics[Current_Topic].resource_end;
  870.     
  871.     if ((whatHit == Next_Button) && (Current_Pict < theMax))    {
  872.         Current_Pict++;
  873.         H_Set_Button_State(Prev_Button, true);
  874.         if (Current_Pict < theMax)    H_Set_Button_State(Next_Button, true);
  875.         else                        H_Set_Button_State(Next_Button, false);
  876.         H_Display_Pict(Current_Pict);
  877.     }
  878.     else if ((whatHit == Prev_Button) && (Current_Pict > theMin))    {
  879.         --Current_Pict;
  880.         H_Set_Button_State(Next_Button, true);
  881.         if (Current_Pict > theMin)    H_Set_Button_State(Prev_Button, true);
  882.         else                        H_Set_Button_State(Prev_Button, false);
  883.         H_Display_Pict(Current_Pict);
  884.     }
  885.     else    SysBeep(10);
  886.         
  887. }    /* H_Scroll_Picture */
  888.  
  889.  
  890.  
  891. void    H_Scroll_Text (short oldValue, short newValue)    {
  892.  
  893.         
  894.     TEScroll(0, (oldValue - newValue), myTEHandle);
  895.  
  896. }    /* H_Scroll_Text */
  897.  
  898.  
  899.  
  900. void    H_Set_Button_State (int itemNum, Boolean state)    {
  901.  
  902.         short        bType;
  903.         Handle        bHandle;
  904.         Rect        bBox;
  905.  
  906.  
  907.     GetDItem(helpPtr, itemNum, &bType, &bHandle, &bBox);
  908.     if (state)        HiliteControl((ControlHandle)bHandle, ON);
  909.     else            HiliteControl((ControlHandle)bHandle, OFF);
  910.     
  911. }    /* H_Set_Button_State */
  912.  
  913.  
  914.  
  915. void    H_User_Message (Str255 theStr)    {
  916.  
  917.         short    mType;
  918.         Handle    mHandle;
  919.         Rect    mBox;
  920.  
  921.  
  922.     GetDItem(helpPtr, Message_Area, &mType, &mHandle, &mBox);
  923.     SetIText(mHandle, theStr);
  924.  // DrawDialog(helpPtr);  --  SetIText() draws the text.
  925.      ValidRect(&mBox);
  926.     
  927. }    /* H_User_Message */
  928.  
  929.  
  930.  
  931. pascal Boolean    H_Modal_Filter (DialogPtr dlg, EventRecord *event, short *itemHit)    {
  932.  
  933.         Boolean            letModalContinueToHandleIt = false,        /* Reverse logic */
  934.                         noFurtherProcessing = true,
  935.                         result;
  936.         ControlHandle    okButton;
  937.         char            key;
  938.         
  939.         
  940.     switch (event->what)    {
  941.     
  942.         case keyDown:
  943.             key = event->message & charCodeMask;
  944.             if ( (key == '\r') || (key == Enter) )        {
  945.                 okButton = GetDefaultButton(dlg);
  946.                 SimulateClick(okButton);
  947.                 result = noFurtherProcessing;
  948.                 *itemHit = ok;
  949.             }
  950.             else    {
  951.                 SysBeep(10);
  952.                 result = letModalContinueToHandleIt;
  953.             }
  954.             break;
  955.             
  956.         default:
  957.             result = letModalContinueToHandleIt;
  958.     
  959.     }    /* end switch */
  960.     
  961.     return (result);
  962.  
  963. }    /* H_Modal_Filter */
  964.  
  965.  
  966.  
  967. pascal void    H_Frame_Alert_Button (DialogPtr dlg, short theItem)    {
  968.  
  969.         
  970.     FrameDefaultButton (dlg);
  971.     
  972. }    /* H_Frame_Alert_Button */
  973.  
  974.  
  975.  
  976. void    H_DrawGrowIcon (ListHandle theList)    {
  977. /* Special routine because the list is INSIDE of another window. */
  978.  
  979.         PenState        pnState;
  980.         RgnHandle        oldClip;
  981.         Boolean            listHasGrowIcon;
  982.         Rect            listGrowRect, tempRect;
  983.         ControlHandle    listScrollBar;
  984.         RGBColor        foreColor;
  985.         AuxCtlHandle    acHndl;
  986.         CCTabHandle        ccTable;
  987.  
  988.  
  989.     listHasGrowIcon = (Boolean) LoWord( (*theList)->refCon );
  990.     if (!listHasGrowIcon)        return;
  991.     
  992.     listGrowRect = (*theList)->rView;
  993.     listGrowRect.left = listGrowRect.right + frame;
  994.     listGrowRect.right = listGrowRect.right  + growBoxSize;
  995.     listGrowRect.top = listGrowRect.bottom + frame;
  996.     listGrowRect.bottom = listGrowRect.bottom + growBoxSize;
  997.     
  998.     if ( (**theList).lActive )        {
  999.         GetPenState(&pnState);
  1000.         oldClip = NewRgn();
  1001.         GetClip(oldClip);
  1002.         ;
  1003.         PenNormal();
  1004.         PenSize(frame, frame);
  1005.         PenPat(&gray);
  1006.         ClipRect(&List_Rect);
  1007.         
  1008.         if (gMac2)        {
  1009.             GetForeColor(&foreColor);
  1010.             
  1011.             if ((**theList).vScroll != nil)
  1012.                 listScrollBar = (**theList).vScroll;
  1013.             else if ((**theList).hScroll != nil)
  1014.                 listScrollBar = (**theList).hScroll;
  1015.             else
  1016.                 listScrollBar = nil;
  1017.             
  1018.             if ((listScrollBar != nil) && GetAuxCtl(listScrollBar, &acHndl))    {
  1019.                 ccTable = (**acHndl).acCTable;
  1020.                 RGBForeColor(& ((**ccTable).ctTable)[cFrameColor].rgb );
  1021.             }
  1022.         }    /* gMac2 */
  1023.  
  1024.         // First the bigger rect at the bottom-right ...
  1025.         tempRect = listGrowRect;
  1026.         tempRect.top = tempRect.top + 5;
  1027.         tempRect.left = tempRect.left + 5;
  1028.         tempRect.right = tempRect.right - 2;
  1029.         tempRect.bottom = tempRect.bottom - 2;
  1030.         FrameRect(&tempRect);
  1031.         
  1032.         // Then the small rect at the topLeft ...
  1033.         tempRect = listGrowRect;
  1034.         tempRect.top = tempRect.top + 3;
  1035.         tempRect.left = tempRect.left + 3;
  1036.         tempRect.right = tempRect.left + 5;
  1037.         tempRect.bottom = tempRect.top + 5;
  1038.         EraseRect(&tempRect);
  1039.         FrameRect(&tempRect);
  1040.  
  1041.         if (gMac2)    RGBForeColor(&foreColor);
  1042.         ;
  1043.         SetClip(oldClip);
  1044.         SetPenState(&pnState);
  1045.     }
  1046.     else    /* List NOT active */    EraseRect(&listGrowRect);
  1047.  
  1048. }    /* H_DrawGrowIcon */
  1049.  
  1050.  
  1051.  
  1052. long    H_GetListScrollValues (ListHandle theList)        {
  1053. /* Returns value of vertical Scroll Bar in High word
  1054. ** and value of horizontal Scroll Bar in low word.
  1055. ** A non-existent or inactive Scroll Bar returns a
  1056. ** value = -1 in the appropriate word.                 */
  1057.  
  1058.         long            high = 0x0000FFFF, low = 0x0000FFFF;
  1059.         ControlHandle    vS, hS;
  1060.         
  1061.     
  1062.     vS = (*theList)->vScroll;
  1063.     hS = (*theList)->hScroll;
  1064.     
  1065.     if ( (vS != nil) && ((**vS).contrlMax > (**vS).contrlMin) )
  1066.         high = (long) GetCtlValue(vS);
  1067.         
  1068.     if ( (hS != nil) && ((**hS).contrlMax > (**hS).contrlMin) )
  1069.         low = (long) GetCtlValue(hS);
  1070.     
  1071.     return ( (high << 16) | low );
  1072.     
  1073. }    /* H_GetListScrollValues */
  1074.  
  1075.  
  1076.  
  1077.  
  1078. /*    { end file "about.c" }  */
  1079.